package top.zhangjianyong;

import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.StrUtil;
import lombok.extern.slf4j.Slf4j;
import top.zhangjianyong.entity.Log;
import top.zhangjianyong.utils.IdWorker;
import top.zhangjianyong.utils.JDBCUtil;
import top.zhangjianyong.utils.RegexUtil;


import java.io.*;
import java.sql.SQLException;
import java.sql.SQLIntegrityConstraintViolationException;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 分析nginx日志
 *
 * @author zhangjianyong
 * @since 2024/7/22 上午11:40
 */
@Slf4j
public class AnalyzeLog {

    private final static String regex = "^(\\S*) - (\\S*) \\[([\\S\\s]*)] \"([^\"]*)\" ([0-9]*) ([0-9]*) \"([^\"]*)\" \"([^\"]*)\"";

    private final static IdWorker idWorker = new IdWorker(1, 1, 1);

    static {
        JDBCUtil.init();
    }

    private final static String insSql = "INSERT IGNORE INTO log(id,remote_addr,remote_user,time_local,request,`status`,body_bytes_sent,http_referer,http_user_agent,md5)\n" + " VALUES(?,?,?,?,?,?,?,?,?,?)";
    private final static String countSql = "SELECT COUNT(1) count FROM `log` WHERE `md5` = ?";

    public static void main(String[] args) {

        String logPath = "/Users/zhangjianyong/IdeaProjects/accesslog";
        String filePrefix = "split";
        logPath = args[0];

        File file = new File(logPath);
        if (!file.isDirectory()) {
            log.info("file is not a directory");
            return;
        }
        File[] files = file.listFiles();
        if (files == null || files.length == 0) {
            log.info("files is empty");
            return;
        }

        log.info("process...");
        Arrays.stream(files)
                .sorted(Comparator.comparing(File::getName))
                .filter(f -> {
                    log.info("filename:{}", f.getName());
                    return f.getName().startsWith(filePrefix);
                })
                .filter(AnalyzeLog::process)
                .forEach(f -> {
                    log.info("delete:{}", f.getName());
                    f.delete();
                });
        log.info("end...");
    }

    private static boolean process(File file) {
        InputStream ins = null;
        BufferedReader br = null;
        try {
            ins = new FileInputStream(file);
            br = new BufferedReader(new InputStreamReader(ins));

            br.lines().parallel()
                    .filter(StrUtil::isNotBlank)
                    .map(line -> {
                        log.info(line);
                        return RegexUtil.matchesAll(line, regex);
                    })
                    // .limit(1)
                    .map(list -> new Log(list, idWorker.nextId()))
                    .forEach(l -> {
                        //插入数据
                        try {
                            log.info("insert...");
                            /*(id,remote_addr,remote_user,time_local,request,`status`,body_bytes_sent,http_referer,http_user_agent,md5)*/
                            JDBCUtil.insert(insSql, l.getId(),
                                    l.getRemoteAddr(), l.getRemoteUser(),
                                    l.getTimeLocal(), l.getRequest(), l.getStatus(),
                                    l.getBodyBytesSent(), l.getHttpReferer(),
                                    l.getHttpUserAgent(), l.getMd5());
                            log.info("add cache...");
                        } catch (SQLIntegrityConstraintViolationException e) {
                            log.error(e.getMessage(), e);
                        } catch (Exception e) {
                            log.info("error: {}", l.getMd5());
                            throw new RuntimeException(e);
                        }
                    });


            return true;
        } catch (FileNotFoundException e) {
            log.error(e.getMessage(), e);
            return false;
        } finally {
            IoUtil.close(ins);
            IoUtil.close(br);
        }
    }
}
